/*
 * seesaw_2008b.c
 *
 * Real-Time Workshop code generation for Simulink model "seesaw_2008b.mdl".
 *
 * Model Version              : 1.48
 * Real-Time Workshop version : 7.2  (R2008b)  04-Aug-2008
 * C source code generated on : Fri Nov 18 17:21:27 2011
 */

#include "seesaw_2008b.h"
#include "seesaw_2008b_private.h"
#include <stdio.h>
#include "seesaw_2008b_dt.h"

/* options for Real-Time Windows Target board 0 */
static double RTWinBoardOptions0[] = {
  1.0,
  0.0,
  0.0,
};

/* list of Real-Time Windows Target boards */
const int RTWinBoardCount = 1;
RTWINBOARD RTWinBoards[1] = {
  { "National_Instruments/PCI-6014", 4294967295U, 3, RTWinBoardOptions0 },
};

/* Block signals (auto storage) */
BlockIO_seesaw_2008b seesaw_2008b_B;

/* Block states (auto storage) */
D_Work_seesaw_2008b seesaw_2008b_DWork;

/* Real-time model */
RT_MODEL_seesaw_2008b seesaw_2008b_M_;
RT_MODEL_seesaw_2008b *seesaw_2008b_M = &seesaw_2008b_M_;
static void rate_scheduler(void);

/*
 * This function updates active task flag for each subrate.
 * The function must be is called at model base rate, hence the
 * generated code self-manages all its subrates.
 */
static void rate_scheduler(void)
{
  /* Compute which subrates run during the next base time step.  Subrates
   * are an integer multiple of the base rate counter.  Therefore, the subtask
   * counter is reset when it reaches its limit (zero means run).
   */
  if (++seesaw_2008b_M->Timing.TaskCounters.TID[2] == 50) {/* Sample time: [0.25s, 0.0s] */
    seesaw_2008b_M->Timing.TaskCounters.TID[2] = 0;
  }

  seesaw_2008b_M->Timing.sampleHits[2] =
    (seesaw_2008b_M->Timing.TaskCounters.TID[2] == 0);
}

/* Model output function */
void seesaw_2008b_output(int_T tid)
{
  /* local block i/o variables */
  real_T rtb_Gain[2];
  real_T rtb_Gain_o;

  {
    real_T rtb_Add2;
    real_T rtb_Add1;
    real_T rtb_Sum_idx;
    real_T rtb_Sum_idx_0;
    real_T rtb_Sum_idx_1;
    real_T rtb_Sum_idx_2;

    /* S-Function Block: <S1>/Analog Input */
    {
      ANALOGIOPARM parm;
      parm.mode = (RANGEMODE) seesaw_2008b_P.AnalogInput_RangeMode;
      parm.rangeidx = seesaw_2008b_P.AnalogInput_VoltRange;
      RTBIO_DriverIO(0, ANALOGINPUT, IOREAD, 2,
                     &seesaw_2008b_P.AnalogInput_Channels[0], rtb_Gain, &parm);
    }

    /* Sum: '<S1>/Add2' incorporates:
     *  Constant: '<S1>/Offset_x (volts)'
     */
    rtb_Add2 = seesaw_2008b_P.Offset_xvolts_Value + rtb_Gain[0];

    /* Gain: '<S1>/Convertion actor' */
    seesaw_2008b_B.Convertionactor = seesaw_2008b_P.Convertionactor_Gain *
      rtb_Add2;

    /* Sum: '<S1>/Add1' incorporates:
     *  Constant: '<S1>/Offset_theta (volt)'
     */
    rtb_Add1 = rtb_Gain[1] + seesaw_2008b_P.Offset_thetavolt_Value;

    /* Gain: '<S1>/Convertion ' */
    seesaw_2008b_B.Convertion = seesaw_2008b_P.Convertion_Gain * rtb_Add1;

    /* Gain: '<S7>/Gain' */
    rtb_Gain[0] = seesaw_2008b_P.Gain_Gain * seesaw_2008b_B.Convertionactor;
    rtb_Gain[1] = seesaw_2008b_P.Gain_Gain * seesaw_2008b_B.Convertion;

    /* Sum: '<S7>/Sum' incorporates:
     *  Gain: '<S7>/Gain1'
     *  UnitDelay: '<S7>/Unit Delay'
     */
    seesaw_2008b_B.Sum[0] = seesaw_2008b_P.Gain1_Gain *
      seesaw_2008b_DWork.UnitDelay_DSTATE[0] + rtb_Gain[0];
    seesaw_2008b_B.Sum[1] = seesaw_2008b_P.Gain1_Gain *
      seesaw_2008b_DWork.UnitDelay_DSTATE[1] + rtb_Gain[1];

    /* S-Function (sfix_tsampmath): '<S3>/TSamp' */

    /* Sample Time Math Block: '<S3>/TSamp'
     *
     * y = u * K     where     K = 1 / ( w * Ts )
     *
     * Input0  Data Type:  Floating Point real_T
     * Output0 Data Type:  Floating Point real_T
     *
     * Parameter: WtEt == Weighted Elapsed Time
     *   Data Type:  Floating Point real_T
     *
     */
    seesaw_2008b_B.TSamp[0] = seesaw_2008b_B.Sum[0] * seesaw_2008b_P.TSamp_WtEt;
    seesaw_2008b_B.TSamp[1] = seesaw_2008b_B.Sum[1] * seesaw_2008b_P.TSamp_WtEt;

    /* Sum: '<S3>/Diff' incorporates:
     *  UnitDelay: '<S3>/UD'
     */
    seesaw_2008b_B.Diff[0] = seesaw_2008b_B.TSamp[0] -
      seesaw_2008b_DWork.UD_DSTATE[0];
    seesaw_2008b_B.Diff[1] = seesaw_2008b_B.TSamp[1] -
      seesaw_2008b_DWork.UD_DSTATE[1];

    /* DiscretePulseGenerator: '<Root>/Pulse Generator' */
    rtb_Gain_o =
      (seesaw_2008b_DWork.clockTickCounter < seesaw_2008b_P.PulseGenerator_Duty &&
       seesaw_2008b_DWork.clockTickCounter >= 0) ?
      seesaw_2008b_P.PulseGenerator_Amp :
      0.0;
    if (seesaw_2008b_DWork.clockTickCounter >=
        seesaw_2008b_P.PulseGenerator_Period-1) {
      seesaw_2008b_DWork.clockTickCounter = 0;
    } else {
      (seesaw_2008b_DWork.clockTickCounter)++;
    }

    /* Switch: '<S6>/SwitchControl' incorporates:
     *  Constant: '<Root>/thetad'
     *  Constant: '<Root>/thetad1'
     *  Constant: '<S6>/Constant'
     */
    if (seesaw_2008b_P.Constant_Value > seesaw_2008b_P.SwitchControl_Threshold)
    {
      rtb_Sum_idx = seesaw_2008b_P.thetad_Value[0];
      rtb_Sum_idx_0 = seesaw_2008b_P.thetad_Value[1];
      rtb_Sum_idx_1 = seesaw_2008b_P.thetad_Value[2];
      rtb_Sum_idx_2 = seesaw_2008b_P.thetad_Value[3];
    } else {
      rtb_Sum_idx = seesaw_2008b_P.thetad1_Value;
      rtb_Sum_idx_0 = rtb_Gain_o;
      rtb_Sum_idx_1 = seesaw_2008b_P.thetad1_Value;
      rtb_Sum_idx_2 = seesaw_2008b_P.thetad1_Value;
    }

    /* Sum: '<Root>/Sum' */
    rtb_Sum_idx = seesaw_2008b_B.Convertionactor - rtb_Sum_idx;
    rtb_Sum_idx_0 = seesaw_2008b_B.Convertion - rtb_Sum_idx_0;
    rtb_Sum_idx_1 = seesaw_2008b_B.Diff[0] - rtb_Sum_idx_1;

    /* Gain: '<Root>/-K' */
    seesaw_2008b_B.K = ((seesaw_2008b_P.K_Gain[0] * rtb_Sum_idx +
                         seesaw_2008b_P.K_Gain[1] * rtb_Sum_idx_0) +
                        seesaw_2008b_P.K_Gain[2] * rtb_Sum_idx_1) +
      (seesaw_2008b_B.Diff[1] - rtb_Sum_idx_2) * seesaw_2008b_P.K_Gain[3];

    /* Switch: '<S5>/SwitchControl' incorporates:
     *  Constant: '<Root>/Off'
     *  Constant: '<S5>/Constant'
     *  Saturate: '<Root>/Saturation -3.5 to 3.5v'
     */
    if (seesaw_2008b_P.Constant_Value_a >
        seesaw_2008b_P.SwitchControl_Threshold_i) {
      rtb_Gain_o = rt_SATURATE(seesaw_2008b_B.K,
        seesaw_2008b_P.Saturation35to35v_LowerSat,
        seesaw_2008b_P.Saturation35to35v_UpperSat);
    } else {
      rtb_Gain_o = seesaw_2008b_P.Off_Value;
    }

    /* Gain: '<S2>/Gain' incorporates:
     *  Saturate: '<S2>/-5v to 5v'
     */
    rtb_Gain_o = seesaw_2008b_P.Gain_Gain_d * rt_SATURATE(rtb_Gain_o,
      seesaw_2008b_P.uvto5v_LowerSat, seesaw_2008b_P.uvto5v_UpperSat);

    /* S-Function Block: <S2>/Analog Output */
    {
      {
        ANALOGIOPARM parm;
        parm.mode = (RANGEMODE) seesaw_2008b_P.AnalogOutput_RangeMode;
        parm.rangeidx = seesaw_2008b_P.AnalogOutput_VoltRange;
        RTBIO_DriverIO(0, ANALOGOUTPUT, IOWRITE, 1,
                       &seesaw_2008b_P.AnalogOutput_Channels, &rtb_Gain_o, &parm);
      }
    }

    if (seesaw_2008b_M->Timing.TaskCounters.TID[2] == 0) {
      /* RateTransition: '<S1>/Rate Transition' */
      seesaw_2008b_B.RateTransition[0] = rtb_Add2;
      seesaw_2008b_B.RateTransition[1] = rtb_Add1;

      /* RateTransition: '<S1>/Rate Transition1' */
      seesaw_2008b_B.RateTransition1[0] = seesaw_2008b_B.Convertionactor;
      seesaw_2008b_B.RateTransition1[1] = seesaw_2008b_B.Convertion;
    }

    if (seesaw_2008b_M->Timing.TaskCounters.TID[2] == 0) {
      /* Gain: '<S4>/Gain' */
      seesaw_2008b_B.Gain = seesaw_2008b_P.Gain_Gain_dx *
        seesaw_2008b_B.RateTransition1[1];
    }
  }

  /* tid is required for a uniform function interface.
   * Argument tid is not used in the function. */
  UNUSED_PARAMETER(tid);
}

/* Model update function */
void seesaw_2008b_update(int_T tid)
{
  /* Update for UnitDelay: '<S7>/Unit Delay' */
  seesaw_2008b_DWork.UnitDelay_DSTATE[0] = seesaw_2008b_B.Sum[0];

  /* Update for UnitDelay: '<S3>/UD' */
  seesaw_2008b_DWork.UD_DSTATE[0] = seesaw_2008b_B.TSamp[0];

  /* Update for UnitDelay: '<S7>/Unit Delay' */
  seesaw_2008b_DWork.UnitDelay_DSTATE[1] = seesaw_2008b_B.Sum[1];

  /* Update for UnitDelay: '<S3>/UD' */
  seesaw_2008b_DWork.UD_DSTATE[1] = seesaw_2008b_B.TSamp[1];

  /* Update absolute time for base rate */
  if (!(++seesaw_2008b_M->Timing.clockTick0))
    ++seesaw_2008b_M->Timing.clockTickH0;
  seesaw_2008b_M->Timing.t[0] = seesaw_2008b_M->Timing.clockTick0 *
    seesaw_2008b_M->Timing.stepSize0 + seesaw_2008b_M->Timing.clockTickH0 *
    seesaw_2008b_M->Timing.stepSize0 * 4294967296.0;

  {
    /* Update absolute timer for sample time: [0.005s, 0.0s] */
    if (!(++seesaw_2008b_M->Timing.clockTick1))
      ++seesaw_2008b_M->Timing.clockTickH1;
    seesaw_2008b_M->Timing.t[1] = seesaw_2008b_M->Timing.clockTick1 *
      seesaw_2008b_M->Timing.stepSize1 + seesaw_2008b_M->Timing.clockTickH1 *
      seesaw_2008b_M->Timing.stepSize1 * 4294967296.0;
  }

  if (seesaw_2008b_M->Timing.TaskCounters.TID[2] == 0) {
    /* Update absolute timer for sample time: [0.25s, 0.0s] */
    if (!(++seesaw_2008b_M->Timing.clockTick2))
      ++seesaw_2008b_M->Timing.clockTickH2;
    seesaw_2008b_M->Timing.t[2] = seesaw_2008b_M->Timing.clockTick2 *
      seesaw_2008b_M->Timing.stepSize2 + seesaw_2008b_M->Timing.clockTickH2 *
      seesaw_2008b_M->Timing.stepSize2 * 4294967296.0;
  }

  rate_scheduler();

  /* tid is required for a uniform function interface.
   * Argument tid is not used in the function. */
  UNUSED_PARAMETER(tid);
}

/* Model initialize function */
void seesaw_2008b_initialize(boolean_T firstTime)
{
  (void)firstTime;

  /* Registration code */

  /* initialize non-finites */
  rt_InitInfAndNaN(sizeof(real_T));

  /* initialize real-time model */
  (void) memset((void *)seesaw_2008b_M,0,
                sizeof(RT_MODEL_seesaw_2008b));

  {
    /* Setup solver object */
    rtsiSetSimTimeStepPtr(&seesaw_2008b_M->solverInfo,
                          &seesaw_2008b_M->Timing.simTimeStep);
    rtsiSetTPtr(&seesaw_2008b_M->solverInfo, &rtmGetTPtr(seesaw_2008b_M));
    rtsiSetStepSizePtr(&seesaw_2008b_M->solverInfo,
                       &seesaw_2008b_M->Timing.stepSize0);
    rtsiSetErrorStatusPtr(&seesaw_2008b_M->solverInfo, (&rtmGetErrorStatus
      (seesaw_2008b_M)));
    rtsiSetRTModelPtr(&seesaw_2008b_M->solverInfo, seesaw_2008b_M);
  }

  rtsiSetSimTimeStep(&seesaw_2008b_M->solverInfo, MAJOR_TIME_STEP);
  rtsiSetSolverName(&seesaw_2008b_M->solverInfo,"FixedStepDiscrete");

  /* Initialize timing info */
  {
    int_T *mdlTsMap = seesaw_2008b_M->Timing.sampleTimeTaskIDArray;
    mdlTsMap[0] = 0;
    mdlTsMap[1] = 1;
    mdlTsMap[2] = 2;
    seesaw_2008b_M->Timing.sampleTimeTaskIDPtr = (&mdlTsMap[0]);
    seesaw_2008b_M->Timing.sampleTimes =
      (&seesaw_2008b_M->Timing.sampleTimesArray[0]);
    seesaw_2008b_M->Timing.offsetTimes =
      (&seesaw_2008b_M->Timing.offsetTimesArray[0]);

    /* task periods */
    seesaw_2008b_M->Timing.sampleTimes[0] = (0.0);
    seesaw_2008b_M->Timing.sampleTimes[1] = (0.005);
    seesaw_2008b_M->Timing.sampleTimes[2] = (0.25);

    /* task offsets */
    seesaw_2008b_M->Timing.offsetTimes[0] = (0.0);
    seesaw_2008b_M->Timing.offsetTimes[1] = (0.0);
    seesaw_2008b_M->Timing.offsetTimes[2] = (0.0);
  }

  rtmSetTPtr(seesaw_2008b_M, &seesaw_2008b_M->Timing.tArray[0]);

  {
    int_T *mdlSampleHits = seesaw_2008b_M->Timing.sampleHitArray;
    mdlSampleHits[0] = 1;
    mdlSampleHits[1] = 1;
    mdlSampleHits[2] = 1;
    seesaw_2008b_M->Timing.sampleHits = (&mdlSampleHits[0]);
  }

  rtmSetTFinal(seesaw_2008b_M, -1);
  seesaw_2008b_M->Timing.stepSize0 = 0.005;
  seesaw_2008b_M->Timing.stepSize1 = 0.005;
  seesaw_2008b_M->Timing.stepSize2 = 0.25;

  /* external mode info */
  seesaw_2008b_M->Sizes.checksums[0] = (2171747911U);
  seesaw_2008b_M->Sizes.checksums[1] = (3236702890U);
  seesaw_2008b_M->Sizes.checksums[2] = (4026085818U);
  seesaw_2008b_M->Sizes.checksums[3] = (1710623978U);

  {
    static const sysRanDType rtAlwaysEnabled = SUBSYS_RAN_BC_ENABLE;
    static RTWExtModeInfo rt_ExtModeInfo;
    static const sysRanDType *systemRan[5];
    seesaw_2008b_M->extModeInfo = (&rt_ExtModeInfo);
    rteiSetSubSystemActiveVectorAddresses(&rt_ExtModeInfo, systemRan);
    systemRan[0] = &rtAlwaysEnabled;
    systemRan[1] = &rtAlwaysEnabled;
    systemRan[2] = &rtAlwaysEnabled;
    systemRan[3] = &rtAlwaysEnabled;
    systemRan[4] = &rtAlwaysEnabled;
    rteiSetModelMappingInfoPtr(&rt_ExtModeInfo,
      &seesaw_2008b_M->SpecialInfo.mappingInfo);
    rteiSetChecksumsPtr(&rt_ExtModeInfo, seesaw_2008b_M->Sizes.checksums);
    rteiSetTPtr(&rt_ExtModeInfo, rtmGetTPtr(seesaw_2008b_M));
  }

  seesaw_2008b_M->solverInfoPtr = (&seesaw_2008b_M->solverInfo);
  seesaw_2008b_M->Timing.stepSize = (0.005);
  rtsiSetFixedStepSize(&seesaw_2008b_M->solverInfo, 0.005);
  rtsiSetSolverMode(&seesaw_2008b_M->solverInfo, SOLVER_MODE_SINGLETASKING);

  /* block I/O */
  seesaw_2008b_M->ModelData.blockIO = ((void *) &seesaw_2008b_B);
  (void) memset(((void *) &seesaw_2008b_B),0,
                sizeof(BlockIO_seesaw_2008b));

  /* parameters */
  seesaw_2008b_M->ModelData.defaultParam = ((real_T *) &seesaw_2008b_P);

  /* states (dwork) */
  seesaw_2008b_M->Work.dwork = ((void *) &seesaw_2008b_DWork);
  (void) memset((void *)&seesaw_2008b_DWork, 0,
                sizeof(D_Work_seesaw_2008b));

  /* data type transition information */
  {
    static DataTypeTransInfo dtInfo;
    (void) memset((char_T *) &dtInfo,0,
                  sizeof(dtInfo));
    seesaw_2008b_M->SpecialInfo.mappingInfo = (&dtInfo);
    dtInfo.numDataTypes = 14;
    dtInfo.dataTypeSizes = &rtDataTypeSizes[0];
    dtInfo.dataTypeNames = &rtDataTypeNames[0];

    /* Block I/O transition table */
    dtInfo.B = &rtBTransTable;

    /* Parameters transition table */
    dtInfo.P = &rtPTransTable;
  }
}

/* Model terminate function */
void seesaw_2008b_terminate(void)
{
  /* S-Function Block: <S2>/Analog Output */
  {
    {
      ANALOGIOPARM parm;
      parm.mode = (RANGEMODE) seesaw_2008b_P.AnalogOutput_RangeMode;
      parm.rangeidx = seesaw_2008b_P.AnalogOutput_VoltRange;
      RTBIO_DriverIO(0, ANALOGOUTPUT, IOWRITE, 1,
                     &seesaw_2008b_P.AnalogOutput_Channels,
                     &seesaw_2008b_P.AnalogOutput_FinalValue, &parm);
    }
  }

  /* External mode */
  rtExtModeShutdown(3);
}

/*========================================================================*
 * Start of GRT compatible call interface                                 *
 *========================================================================*/
void MdlOutputs(int_T tid)
{
  seesaw_2008b_output(tid);
}

void MdlUpdate(int_T tid)
{
  seesaw_2008b_update(tid);
}

void MdlInitializeSizes(void)
{
  seesaw_2008b_M->Sizes.numContStates = (0);/* Number of continuous states */
  seesaw_2008b_M->Sizes.numY = (0);    /* Number of model outputs */
  seesaw_2008b_M->Sizes.numU = (0);    /* Number of model inputs */
  seesaw_2008b_M->Sizes.sysDirFeedThru = (0);/* The model is not direct feedthrough */
  seesaw_2008b_M->Sizes.numSampTimes = (3);/* Number of sample times */
  seesaw_2008b_M->Sizes.numBlocks = (43);/* Number of blocks */
  seesaw_2008b_M->Sizes.numBlockIO = (9);/* Number of block outputs */
  seesaw_2008b_M->Sizes.numBlockPrms = (41);/* Sum of parameter "widths" */
}

void MdlInitializeSampleTimes(void)
{
}

void MdlInitialize(void)
{
  /* InitializeConditions for UnitDelay: '<S7>/Unit Delay' */
  seesaw_2008b_DWork.UnitDelay_DSTATE[0] = seesaw_2008b_P.UnitDelay_X0;

  /* InitializeConditions for UnitDelay: '<S3>/UD' */
  seesaw_2008b_DWork.UD_DSTATE[0] = seesaw_2008b_P.UD_X0;

  /* InitializeConditions for UnitDelay: '<S7>/Unit Delay' */
  seesaw_2008b_DWork.UnitDelay_DSTATE[1] = seesaw_2008b_P.UnitDelay_X0;

  /* InitializeConditions for UnitDelay: '<S3>/UD' */
  seesaw_2008b_DWork.UD_DSTATE[1] = seesaw_2008b_P.UD_X0;
}

void MdlStart(void)
{
  /* DiscretePulseGenerator Block: '<Root>/Pulse Generator' */
  {
    int_T Ns;
    Ns = 0;
    if (Ns <= 0) {
      seesaw_2008b_DWork.clockTickCounter = Ns;
    } else {
      seesaw_2008b_DWork.clockTickCounter = Ns - (int_T)
        (seesaw_2008b_P.PulseGenerator_Period*floor((real_T)Ns /
          seesaw_2008b_P.PulseGenerator_Period));
    }
  }

  /* S-Function Block: <S2>/Analog Output */
  {
    {
      ANALOGIOPARM parm;
      parm.mode = (RANGEMODE) seesaw_2008b_P.AnalogOutput_RangeMode;
      parm.rangeidx = seesaw_2008b_P.AnalogOutput_VoltRange;
      RTBIO_DriverIO(0, ANALOGOUTPUT, IOWRITE, 1,
                     &seesaw_2008b_P.AnalogOutput_Channels,
                     &seesaw_2008b_P.AnalogOutput_InitialValue, &parm);
    }
  }

  MdlInitialize();
}

RT_MODEL_seesaw_2008b *seesaw_2008b(void)
{
  seesaw_2008b_initialize(1);
  return seesaw_2008b_M;
}

void MdlTerminate(void)
{
  seesaw_2008b_terminate();
}

/*========================================================================*
 * End of GRT compatible call interface                                   *
 *========================================================================*/
